<?php
cmspad_import('util.PortletUtil');
class cmspad_dispatcher_default implements IDispatcher {
	
	private $portal;
	
	public function __construct($portal = 'DefaultPortal'){
		$this->portal = $portal;
	}
	
	/**
	 * @see IDispatcher::dispatch()
	 *
	 * @param string $pathinfo
	 */
	public function dispatch($pathinfo){
		$portletInfo = $this->parsePath($pathinfo);
		if(!$portletInfo){
			return false;
		}
		$contents = call_user_func($portletInfo[0],$portletInfo[1]);
		if($contents){
			echo $contents;
		}
		return true;
	}
	
	/**
	 * @see IDispatcher::hyperlink()
	 *
	 * @param string $portlet
	 * @param string $mehtod
	 * @param array $params
	 * @return string
	 */
	public function hyperlink($portlet = null,$method = null,$params = null){
		global $_CONFIG;
		if(!$portlet){
			$portlet = $this->portal;
		}
		$url = '';
		$applyAlias = false;
		if($portlet){
			if($portlet != $this->portal){
				$url .= '/' . $portlet;
				$applyAlias = true;
			}
			if($method && $method != $portlet){
				$url .= '/' . $method;
			}
			if($params){
				$url .= '/' . implode('/',$params);
			}
		}
		if($applyAlias){
			$url = self::applyAlias($url, true);
		}
		if(isset($_CONFIG['DISPATCH']['SCRIPT'])){
			if(substr($_CONFIG['DISPATCH']['SCRIPT'], -1) == '/'){
				$url = substr($_CONFIG['DISPATCH']['SCRIPT'], 0, -1) . $url;
			}else{
				$url = $_CONFIG['DISPATCH']['SCRIPT'] . $url;
			}
		}else{
			$scriptName = isset($_SERVER['ORIG_SCRIPT_NAME'])?$_SERVER['ORIG_SCRIPT_NAME']:(isset($_SERVER['SCRIPT_NAME'])?$_SERVER['SCRIPT_NAME']:'');
			$url = $scriptName . $url;
		}
		return $url;
	}
	
	private function parsePath($pathinfo){
		while(strpos($pathinfo,'//') !== false){
			$pathinfo = str_replace('//','/',$pathinfo);
		}
		$pathinfo = trim($pathinfo,' /');
		if(empty($pathinfo)){
			$pathinfo = $this->portal . '/' . $this->portal;
		}
		$pathinfo = self::applyAlias($pathinfo, false);
		$arr = explode('/',$pathinfo);
		if(count($arr) > 0){
			$portlet = $arr[0];
			$portletObj = PortletUtil::newObject($portlet);
			if($portletObj === null || $portletObj === false){
				$portletObj = PortletUtil::newObject($portlet = $this->portal);
			}else{
				array_shift($arr);
			}
		}
		if($portletObj === null || $portletObj === false){
			return false;
		}
		if(count($arr) > 0){
			$portletArr = PortletUtil::newMethod($portletObj,'page' . ucfirst($arr[0]));
			if($portletArr === null || $portletArr === false){
				$portletArr = PortletUtil::newMethod($portletObj,'page' . ucfirst($portlet));
			}else{
				array_shift($arr);
			}
			$portletArg = $arr;
		}else{
			$portletArr = PortletUtil::newMethod($portletObj,'page' . ucfirst($portlet));
			$portletArg = array();
		}
		if($portletArr === null || $portletArr === false){
			return false;
		}
		return array($portletArr,$portletArg);
	}
	
	private static function applyAlias($pathinfo,$resolve = false){
		global $_CONFIG;
		if(isset($_CONFIG['DISPATCH']['ALIAS'])){
			$alias = $_CONFIG['DISPATCH']['ALIAS'];
			if(is_array($alias)){
				foreach($alias as $k=>$v){
					$aliasName = trim($k);
					$aliasPath = str_replace('.','/',trim($v, ' ./\\'));
					if($resolve){
						$aliasSize = strlen($aliasPath);
						if(substr($pathinfo,1,$aliasSize) == $aliasPath){
							// If pathinfo length equals to alias name(/hello) or the next char is '/'(/hello/123/456), replace it.
							if(strlen($pathinfo) - 1 == $aliasSize || substr($pathinfo,$aliasSize + 1,1) == '/'){
								$pathinfo = '/'.$aliasName . substr($pathinfo,$aliasSize + 1);
								break;
							}
						}
					}else{
						$aliasSize = strlen($aliasName);
						if(substr($pathinfo,0,$aliasSize) == $aliasName){
							// If pathinfo length equals to alias name(/hello) or the next char is '/'(/hello/123/456), replace it.
							if(strlen($pathinfo) == $aliasSize || substr($pathinfo,$aliasSize,1) == '/'){
								$pathinfo = $aliasPath . substr($pathinfo,$aliasSize);
								break;
							}
						}
					}
				}
			}
		}
		return $pathinfo;
	}
}
?>